#include "cameraconfig.h"
#include "redismanager.h"

//全局相机类型映射
std::map<std::string, std::string> g_mapCameraName;
std::map<std::string, int> g_mapCameraType;


static uint64_t cbTimeout(void *user_data)
{
    int delayMsec = 0;

    CameraConfig *config = static_cast<CameraConfig *>(user_data);
    if(config != nullptr)
    {
        delayMsec = config->m_delayMsec;
        config->doReconnect();
    }

    //redis重连
    RedisManager::getInstance()->autoReconnect();

    return delayMsec;
}

CameraConfig::CameraConfig()
{
    m_timerThread = mk_thread_from_pool();
    if(m_timerThread)
    {
        m_timer = mk_timer_create(m_timerThread, m_delayMsec, cbTimeout, this);
    }
}

CameraConfig::~CameraConfig()
{
    if(m_timer)
    {
        mk_timer_release(m_timer);
    }
}

void CameraConfig::initConfig(const string &configFile)
{
    if(configFile.empty())
    {
        log_printf(LOG_LEV, "ConfigFile is empty %s", configFile.c_str());
        return;
    }

    Json::Value root;
    std::ifstream ifs;
    ifs.open(configFile);

    Json::CharReaderBuilder builder;
    builder["collectComments"] = true;
    JSONCPP_STRING errs;
    if (!parseFromStream(builder, ifs, &root, &errs))
    {
        log_printf(LOG_LEV, "parseFromStream %s", errs.c_str());
        return ;
    }

    m_mapCamInfos.clear();

    //解析camera信息
    if (root["cameras"].isArray())
    {
        Json::Value infos = root["cameras"];

        for (unsigned int i = 0; i < infos.size(); i++)
        {
            STU_CAMERAINFO info;
            info.sourceUrl = infos[i]["sourceUrl"].asString();
            info.app = infos[i]["app"].asString();
            info.stream = infos[i]["streamName"].asString();
            info.protocal = infos[i]["protocal"].asInt();
            info.cameraType = infos[i]["cameraType"].asInt();
            info.cameraName = infos[i]["cameraName"].asString();
            info.enable = infos[i]["enable"].asInt();
            info.record = infos[i]["record"].asInt();

            //如果未开启该流
            if(0 == info.enable)
            {
                continue;
            }

            //如果是usb设备
            char usbInfo[128] = {0};
            if (info.protocal >= 10)
            {
                info.inWidth = infos[i]["inWidth"].asInt();
                info.inHeight = infos[i]["inHeight"].asInt();
                info.inFPS = infos[i]["inFPS"].asInt();
                info.outWidth = infos[i]["outWidth"].asInt();
                info.outHeight = infos[i]["outHeight"].asInt();
                info.outFPS = infos[i]["outFPS"].asInt();
                info.devName = infos[i]["devName"].asString();
                info.outBitrate = infos[i]["outBitrate"].asInt();
                info.outH264 = infos[i]["outH264"].asInt();

                sprintf(usbInfo, "IS_USB:%s %d %d %d %d %d", info.devName.c_str(), info.outWidth, info.outHeight, info.outFPS, info.outBitrate, info.outH264);
            }

            log_printf(LOG_LEV, "StreamInfo: %s %s %s %d %s %d %d %d %s", info.sourceUrl.c_str(), info.app.c_str(), info.stream.c_str()
                                                                     , info.cameraType, info.cameraName.c_str(), info.record
                                                                     , info.enable, info.protocal, usbInfo);

            //类型map记录相关信息
            std::string app = info.app;
            std::string key = app + "/" + info.stream;
            if(info.cameraName.empty())
            {
                info.cameraName = "none";
            }

            g_mapCameraName.insert(std::make_pair(key, info.cameraName));
            g_mapCameraType.insert(std::make_pair(key, info.cameraType));

            //记录相机信息
            m_mapCamInfos[key] = info;
        }
    }
}

void CameraConfig::startProxyPull()
{
    for(auto temp : m_mapCamInfos)
    {
        std::string key = temp.first;
        STU_CAMERAINFO info = temp.second;

        if(0 == info.protocal)
        {
            //rtsp
            auto player = mk_proxy_player_create("", info.app.c_str(), info.stream.c_str(), 0, info.record);
            mk_proxy_player_play(player, info.sourceUrl.c_str());

            std::string app = info.app;
            std::string key = app + "/" + info.stream;
            m_rtspProxys.insert(std::pair<string, mk_proxy_player>(key, player));
        }
        else if(1 == info.protocal)
        {
            //文件
            FileSource *file = new FileSource();
            file->setParam(info);
            file->initMediaSource();
            file->startTask();
            m_fileProxys.insert(std::pair<string, FileSource *>(key, file));
        }
        else if(10 <= info.protocal)
        {
            //设备相机
            Device *device = new Device();
            device->setDeviceParam(info);
            device->initMediaSource();
            device->startTask();
            m_usbProxys.insert(std::pair<string, Device *>(key, device));
        }
    }

}

void CameraConfig::stopProxyPull()
{
    log_printf(LOG_LEV, "开始关闭rtsp代理 个数=%d", m_rtspProxys.size());
    for (auto proxyplayer: m_rtspProxys)
    {
        mk_proxy_player_release(proxyplayer.second);
        proxyplayer.second = nullptr;
    }
    m_rtspProxys.clear();

    log_printf(LOG_LEV, "开始关闭device代理 个数=%d", m_usbProxys.size());
    vector<Device *> vecDevice;
    for (auto usbDevice: m_usbProxys)
    {
        usbDevice.second->stopTask();
        vecDevice.push_back(usbDevice.second);
    }
    for (auto device: vecDevice)
    {
        delete device;
        device = nullptr;
    }
    m_usbProxys.clear();

    log_printf(LOG_LEV, "开始关闭fileSource代理 个数=%d", m_fileProxys.size());
    vector<FileSource *> vecFile;
    for (auto fileSource: m_fileProxys)
    {
        fileSource.second->stopTask();
        vecFile.push_back(fileSource.second);
    }
    for (auto file: vecFile)
    {
        delete file;
        file = nullptr;
    }
    m_fileProxys.clear();
}

void CameraConfig::doReconnect()
{
    //rtsp流已做逻辑

    //对于设备类做重连逻辑
    for (auto usbDevice: m_usbProxys)
    {
        if(!usbDevice.second->m_isRuning)
        {
            usbDevice.second->autoReconnect();
        }
    }

    //对于文件类做重连逻辑
    for (auto file: m_fileProxys)
    {
        if(!file.second->m_isRuning)
        {
            file.second->autoReconnect();
        }
    }
}

void CameraConfig::proxyPullTest()
{
    //代理拉流
    std::string srcUrl = "rtsp://192.168.1.104:10554/driver/cam";
    std::string app = "live";
    std::string stream = "test";
    std::string key = app + "/" + stream;
    mk_proxy_player player = mk_proxy_player_create3("", app.c_str(), stream.c_str(), 0, 1, -1);
    mk_proxy_player_play(player, srcUrl.c_str());
    m_rtspProxys.insert(std::make_pair(key, player));
    log_printf(LOG_LEV, "测试代理拉流 %s", srcUrl.c_str());
}
